package com.allwees.bs.c.module.order.chain.create.handler;

import com.allwees.bs.c.module.order.chain.create.request.OrderCreateRequest;
import com.allwees.bs.c.module.order.chain.create.request.OrderItemCreateRequest;
import com.allwees.bs.c.module.order.entity.OrderEntity;
import com.allwees.bs.c.module.order.entity.OrderItemEntity;
import com.allwees.bs.c.module.order.repository.OrderFlowRepository;
import com.allwees.bs.c.module.order.repository.OrderItemRepository;
import com.allwees.bs.c.module.order.repository.OrderRepository;
import com.allwees.bs.c.module.order.util.OrderFlowUtil;
import com.allwees.bs.c.module.user.entity.ShippingAddressEntity;
import com.allwees.bs.c.module.user.repository.ShippingAddressRepository;
import com.allwees.bs.c.module.user.repository.UserRepository;
import com.allwees.bs.core.model.order.config.ScheduleTimeProperties;
import com.allwees.bs.core.model.order.wf.order.EOrderAction;
import com.allwees.bs.core.model.order.wf.order.EOrderItemAction;
import com.allwees.bs.core.model.order.wf.order.EOrderItemState;
import com.allwees.bs.core.model.order.wf.order.EOrderState;
import com.allwees.bs.core.modelbase.constant.ResultEnum;
import com.allwees.bs.core.modelbase.exception.BusinessException;
import com.allwees.core.common.context.AbstractHandler;
import com.allwees.core.common.util.DateUtil;
import com.allwees.core.common.util.UuidUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

@Component
public class OrderSaveHandler extends AbstractHandler<OrderCreateRequest> {

	@Autowired
	private OrderRepository orderRepository;
	@Autowired
	private OrderItemRepository orderItemRepository;
	@Autowired
	private OrderFlowRepository orderFlowRepository;
	@Autowired
	private ShippingAddressRepository shippingAddressRepository;
	@Autowired
	private UserRepository userRepository;
	@Autowired
	private ScheduleTimeProperties scheduleTimeProperties;

    @Override
    public OrderCreateRequest handler(OrderCreateRequest request) {
        if(request.isCheckOrder()){
            return request;
        }
        OrderEntity order = new OrderEntity();

        _setBase(order, request);
        _setShippingAddress(request.getShippingAddressUuid(), order);

        order.setOrderChannelUuid(request.getOrderChannelUuid());
        orderRepository.save(order);

        _saveOrderFlow(order);
        _saveOrderItems(request.getUserUuid(), order, request);

        request.setUuid(order.getUuid());
        request.setNo(order.getNo());

       return doNext(request);
    }

    private void _setBase(OrderEntity order, OrderCreateRequest request) {
        BeanUtils.copyProperties(request, order);

        order.setState(EOrderState.START);
        order.signal(EOrderAction.USER_CREATE);

        order.setUuid(UuidUtil.generate());
        order.setNo(_genOrderNo());

        order.setPayed(false);
        order.setSynced(false);

        order.setUserUuid(request.getUserUuid());
        order.setNewUser(userRepository.hasOrder(request.getUserUuid()) == null);
        order.setType(request.getOrderType());
        order.setPaymentExpiredAt(DateUtil.addSeconds(DateUtil.now(), scheduleTimeProperties.getOrderUnPaidAutoCancelSecond()));

        order.setMainPhoto(request.getItems().get(0).getProductPhoto());
        order.setCurrency(request.getItems().get(0).getCurrency());
        order.setSum(request.getItems().stream().mapToInt(OrderItemCreateRequest::getQuantity).sum());

        int size = request.getItems().size();
        order.setShippedCount(0);
        order.setQuantity(size);

        if (!StringUtils.isBlank(request.getUserCouponUuid())) {
            order.setUserCouponUuid(request.getUserCouponUuid());
        }
        if (!StringUtils.isBlank(request.getPromoCode())) {
            order.setPromoCode(request.getPromoCode());
        }
    }

    private void _setShippingAddress(String shippingAddressUuid, OrderEntity order) {
        ShippingAddressEntity shippingAddress = this.shippingAddressRepository.getByUuid(shippingAddressUuid);
        if (shippingAddress == null) {
            throw BusinessException.getInstance(ResultEnum.NOT_FOUND);
        }

        order.setShippingAddressUuid(shippingAddressUuid);
        order.setShippingAddressFirstName(shippingAddress.getFirstName());
        order.setShippingAddressLastName(shippingAddress.getLastName());
        order.setShippingAddressItu(shippingAddress.getItu());
        order.setShippingAddressPhone(shippingAddress.getPhone());
        order.setShippingAddressCountry(shippingAddress.getCountry());
        order.setShippingAddressProvince(shippingAddress.getProvince());
        order.setShippingAddressCity(shippingAddress.getCity());
        order.setShippingAddressZipCode(shippingAddress.getZipCode());
        order.setShippingAddressLine1(shippingAddress.getAddressLine1());
        order.setShippingAddressLine2(shippingAddress.getAddressLine2());
    }

    private List<OrderItemEntity> _saveOrderItems(String userUuid, OrderEntity order, OrderCreateRequest request) {
        List<OrderItemEntity> orderItems = new ArrayList<>(request.getItems().size());

        for (OrderItemCreateRequest item : request.getItems()) {
            item.setUuid(UuidUtil.generate());

            OrderItemEntity orderItem = new OrderItemEntity();
            //拷贝bean
            BeanUtils.copyProperties(item, orderItem);

            orderItem.setState(EOrderItemState.START);
            orderItem.signal(EOrderItemAction.USER_CREATE);

            orderItem.setInviterUserUuid(order.getInviterUserUuid());
            orderItem.setUserUuid(userUuid);
            orderItem.setOrderNo(order.getNo());
            orderItem.setDefNo(item.getDefNo());
            orderItem.setOrderUuid(order.getUuid());
            orderItem.setRefunded(false);
            orderItem.setCanceled(false);
            orderItem.setNewUser(order.getNewUser());
            orderItem.setPlatform(order.getPlatform());
            orderItems.add(orderItem);
        }

        orderItemRepository.saveAll(orderItems);

        return orderItems;
    }

    private void _saveOrderFlow(OrderEntity order) {
        orderFlowRepository.save(OrderFlowUtil.generate(order));
    }

    private String _genOrderNo(){
        String[] idd = UUID.randomUUID().toString().split("-");
        return idd[0] + idd[1] + idd[4];
    }
}
